package org.plan;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.htmlunit.WebClient;
import org.htmlunit.html.*;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PlanCrawler {
    static Map<String, SchoolPlan> schoolCollected = new HashMap();


    private static void exportToCSV(String fileName) {
        try (FileWriter writer = new FileWriter(fileName);
             CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader("School Name", "Province", "Address", "Sponsor", "Plan Code", "Plan Name", "Subject Required", "Head Count", "Language Required", "Years", "Tuition Fee"))) {

            for (Map.Entry<String, SchoolPlan> entry : schoolCollected.entrySet()) {
                SchoolPlan schoolPlan = entry.getValue();
                for (Plan plan : schoolPlan.getPlans()) {
                    csvPrinter.printRecord(
                            schoolPlan.getSchoolName(),
                            schoolPlan.getSchoolProvince(),
                            schoolPlan.getSchoolAddress(),
                            schoolPlan.getSponsor(),
                            plan.getPlanCode(),
                            plan.getPlanName(),
                            plan.getSubjectRequired(),
                            plan.getHeadCount(),
                            plan.getLanguageRequired(),
                            plan.getYears(),
                            plan.getTuitionFee()
                    );
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static boolean isSchoolRow(HtmlTableRow row){
        return row.getCells().size() == 6;
    }

    private static boolean isPlanRow(HtmlTableRow row) {
        List<HtmlTableCell> cells = row.getCells();
        for (HtmlTableCell cell : cells) {
            if (cell.getAttribute("class").equals("title_p")) {
                return true;
            }
        }
        return false;
    }

    private static void collectSchoolPlan(String schoolName, HtmlPage page){
        List<HtmlElement> elements = page.getByXPath(".//td[@class='title_px']");
        
        String schoolProvince = elements.get(0).getTextContent();
        String schoolAddress = elements.get(2).getTextContent();
        String sponsor = elements.get(1).getTextContent();
        SchoolPlan schoolPlan = new SchoolPlan(schoolName, schoolProvince, schoolAddress, sponsor);

        HtmlTable  planTable =(HtmlTable)page.getByXPath(".//table[@class='case']").get(0);
        for (HtmlTableRow row : planTable.getRows()) {
            if(isPlanRow(row)){
                List<HtmlTableCell> cells = row.getCells();

                String planCode = cells.get(0).getTextContent();
                String planName = cells.get(1).getTextContent();
                String subjectRequired = cells.get(2).getTextContent();
                String headCount = cells.get(4).getTextContent();
                String languageRequired = cells.get(7).getTextContent();
                String years = cells.get(5).getTextContent();
                String tuitionFee = cells.get(6).getTextContent();

               schoolPlan.addPlan(new Plan(planCode, planName, subjectRequired, headCount, languageRequired, years, tuitionFee));
            }

        }
        schoolCollected.put(schoolName, schoolPlan);
    }

    private static void loadFromCSV(String fileName) {
        try (FileReader reader = new FileReader(fileName);
             CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withHeader("School Name", "Province", "Address", "Sponsor", "Plan Code", "Plan Name", "Subject Required", "Head Count", "Language Required", "Years", "Tuition Fee").withSkipHeaderRecord())) {

            for (CSVRecord record : csvParser) {
                String schoolName = record.get("School Name");
                String schoolProvince = record.get("Province");
                String schoolAddress = record.get("Address");
                String sponsor = record.get("Sponsor");

                SchoolPlan schoolPlan = schoolCollected.getOrDefault(schoolName, new SchoolPlan(schoolName, schoolProvince, schoolAddress, sponsor));

                String planCode = record.get("Plan Code");
                String planName = record.get("Plan Name");
                String subjectRequired = record.get("Subject Required");
                String headCount = record.get("Head Count");
                String languageRequired = record.get("Language Required");
                String years = record.get("Years");
                String tuitionFee = record.get("Tuition Fee");

                schoolPlan.addPlan(new Plan(planCode, planName, subjectRequired, headCount, languageRequired, years, tuitionFee));
                schoolCollected.put(schoolName, schoolPlan);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        int delaySecond = 5000;
        boolean hasMorePage = true;

        // 加载CSV中的数据到schoolCollected中
        loadFromCSV("plans.csv");

        // 打开招生计划页面  https://query.bjeea.cn/queryService/rest/plan/115
        try (final WebClient webClient = new WebClient()) {
            webClient.getOptions().setUseInsecureSSL(true);

            HtmlPage page = webClient.getPage("https://query.bjeea.cn/queryService/rest/plan/115");

            while(hasMorePage){
                Thread.currentThread().sleep(delaySecond);
                // 使用XPath获取包含学校信息的表格
                HtmlTable table = (HtmlTable) page.getByXPath("//*[@id='nav_menu_con1']/table/tbody/tr[4]/td/table").get(0);

                // 遍历表格行，提取学校名称和链接
                for (HtmlTableRow row: table.getRows()) {
                    if (isSchoolRow(row)) {
                        List<HtmlAnchor> anchors = row.getByXPath(".//a");
                        for (HtmlAnchor anchor : anchors) {
                            String schoolName = anchor.getTextContent();

                            if (!schoolCollected.containsKey(schoolName)) {
                                System.out.println(schoolName);
                                Thread.currentThread().sleep(delaySecond);
                                // 点击学校链接，打开学校招生计划页面
                                HtmlPage schoolPage = anchor.click();
                                collectSchoolPlan(schoolName, schoolPage);
                                schoolPage.cleanUp();

                            }else{
                                System.out.println(schoolName+" is in map.");
                            }
                        }
                    }
                }
                // 检查是否有下一页
                HtmlListItem nextPageElement = (HtmlListItem) page.getByXPath("//*[@class='pagination']/ul[2]/li[3]").get(0);
                if (nextPageElement != null && !nextPageElement.getAttribute("class").contains("disabled")) {
                    HtmlAnchor nextPageAnchor = (HtmlAnchor) nextPageElement.getFirstByXPath(".//a");
                    if (nextPageAnchor != null) {
                        Thread.currentThread().sleep(delaySecond);
                        // 给page重新赋值
                        page = nextPageAnchor.click();
                    }
                }else{
                    hasMorePage = false;
                    System.out.println("No more pages.");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // export plans to csv
            exportToCSV("plans.csv");
        }



    }
}